﻿module iinterface;

import core.stdc.stdio;
import core.stdc.string;
import std.c.windows.windows;

import libsocket;

extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleDtor();
extern (C) void _moduleUnitTests();

//连接控制
enum SOC_CTRL:int{
	ADD=0x01,//添加一个连接
	DEL=0x02,//删除一个连接
}
//错误
enum SOC_ERR:int{
	OK    =0x00,//操作成功
	FREEOK=0x01,//关闭网络成功
	NOINIT=0x02,//未初始化
	PARMER=0x03,//参数异常
	CREATE=0x04,//创建连接错误
	NOLINK=0x05,//无此连接
	ADDER =0x06,//添加链接失败
	DELER =0x07,//删除链接失败
	UNCTRL=0x08,//不支持的操作
	UNKNOW=0xFF,//未知错误
}
extern (C){
	typedef void (*TFunc)(uint,ubyte *,uint,int);
}

HINSTANCE     g_hInst;   //全局动态库句柄
TLibSocket    gLibSoc;   //全局网络库句柄
TStandardCall gSC;       //全局标准回调类

class TStandardCall:TNetCall{
private:
	TFunc gF;
public:
	~this(){
		gF=null;
	}
	void SetCB(TFunc fb){
		gF=fb;
	}
	int GetData(uint key,ubyte[] buf,uint len){
		if (gF !is null){
			gF(key,buf.ptr,len,0);
		}
		return 0;
	}

	int GetEevents(uint key,int Ev){
		if (gF !is null)
			gF(key,null,0,Ev);
		return 0;
	}
}
//这里dll接口必须以C的ABI接口导出
extern (C){
export int socket_init()
{
	if (gSC is null)
		gSC=new TStandardCall;
	if (gLibSoc is null){
		gLibSoc=new TLibSocket(gSC);
		if (gLibSoc.Start(0) is false)
			return SOC_ERR.NOINIT;
	}
	return SOC_ERR.OK;
}

export int socket_free()
{
	if (gLibSoc !is null){
		gLibSoc.Shutdown();
		delete gLibSoc;
		gLibSoc=null;
	}
	if (gSC !is null){
		delete gSC;
		gSC    =null;
	}
	return SOC_ERR.FREEOK;
}

export int socket_create(char *strAddress,ubyte slen,ushort uPort,ubyte uSvrType,uint *server)
{
	if (!gSC || !gLibSoc)
		return SOC_ERR.NOINIT;
	if (!strAddress || slen>60)
		return SOC_ERR.PARMER;
	if (!server || uPort>=65535)
		return SOC_ERR.PARMER;
	char[] addr;
	addr.length=slen;
	memcpy(addr.ptr,strAddress,slen);
	uint ret=gLibSoc.CreateSocket(addr,uPort,uSvrType);
	if (!ret)
		return SOC_ERR.CREATE;
	*server=ret;
	return SOC_ERR.OK;
}

export int socket_ctrl(uint key,int flag)
{
	bool ret=false;

	if (!gSC || !gLibSoc)
		return SOC_ERR.NOINIT;
	if (SOC_CTRL.ADD==flag){
		return SOC_ERR.UNCTRL;
	}
	if (SOC_CTRL.DEL==flag){
		ret=gLibSoc.CloseSocket(key);
		if (ret)
			return SOC_ERR.OK;
		else
			return SOC_ERR.DELER;
	}
	return SOC_ERR.UNCTRL;
}

export int socket_wait()
{
	if (!gSC || !gLibSoc)
		return SOC_ERR.NOINIT;
	return SOC_ERR.OK;
}

export int socket_event(TFunc fb)
{
	if (!gSC || !gLibSoc)
		return SOC_ERR.NOINIT;
	gSC.SetCB=fb;
	return SOC_ERR.OK;
}
}
extern (Windows):
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved){
    switch (ulReason){
	case DLL_PROCESS_ATTACH:
		gc_init();
	    _minit();
	    _moduleCtor();
		break;

	case DLL_PROCESS_DETACH:
		gc_term();
		break;

	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
		// Multiple threads not supported yet
		return false;
    }
    g_hInst=hInstance;
    return true;
}

